///////////////////////////////////////////////////////////////////////////////
//
//  This file is part of MathLib.NET.
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//  
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//  
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library;  If not, see 
//  <http://www.gnu.org/licenses/>.
//
///////////////////////////////////////////////////////////////////////////////

using ILNumerics;
using ILNumerics.BuiltInFunctions;

// Basic Information functions
// ===========================
//
// disp - Display text or array 
// display - Display text or array (overloaded method) 
// iscolumn - Determine whether input is column vector 
// isempty - Determine whether array is empty 
// isequal - Test arrays for equality 
// isequalwithequalnans - Test arrays for equality, treating NaNs as equal 
// isfinite - Array elements that are finite 
// isfloat - Determine whether input is floating-point array 
// isinf - Array elements that are infinite 
// isinteger - Determine whether input is integer array 
// islogical - Determine whether input is logical array 
// ismatrix - Determine whether input is matrix 
// isnan - Array elements that are NaN 
// isnumeric - Determine whether input is numeric array 
// isrow - Determine whether input is row vector 
// isscalar - Determine whether input is scalar 
// issparse - Determine whether input is sparse 
// isvector - Determine whether input is vector 
// length - Length of vector or largest array dimension 
// max - Largest elements in array 
// min - Smallest elements in array 
// ndims - Number of array dimensions 
// numel - Number of elements in array or subscripted array expression 
// size - Array dimensions 

namespace MathLib
{
    /// <summary>
    /// Basic information functions.
    /// </summary>
    public partial class MLMath
    {
        /// <summary>
        /// Determine if an object is an array.
        /// </summary>
        /// <param name="obj">Object to test</param>
        /// <returns>true if array, otherwise false</returns>
        public static bool isarray(object obj)
        {
            return obj is ILBaseArray;
        }

        /// <summary>
        /// Determine if array is column vector.
        /// </summary>
        /// <param name="array">Array to test</param>
        /// <returns>true if column vector, otherwise false</returns>
        public static bool iscolumn(ILBaseArray array)
        {
            return array.IsColumnVector;
        }

        /// <summary>
        /// Determine if array is row vector.
        /// </summary>
        /// <param name="array">Array to test</param>
        /// <returns>true if row vector, otherwise false</returns>
        public static bool isrow(ILBaseArray array)
        {
            return array.IsRowVector;
        }

        /// <summary>
        /// Determine if array is scalar.
        /// </summary>
        /// <param name="array">Array to test</param>
        /// <returns>true if scalar, otherwise false</returns>
        public static bool isscalar(ILBaseArray array)
        {
            return array.IsScalar;
        }

        /// <summary>
        /// Determine if array is a vector.
        /// </summary>
        /// <param name="array">Array to test</param>
        /// <returns>true if a vector, otherwise false</returns>
        public static bool isvector(ILBaseArray array)
        {
            return array.IsVector;
        }

        /// <summary>
        /// Determine if array is matrix.
        /// </summary>
        /// <param name="array">Array to test</param>
        /// <returns>true if matrix, otherwise false</returns>
        public static bool ismatrix(ILBaseArray array)
        {
            return array.IsMatrix;
        }

        /// <summary>
        /// Returns whether the given array is empty or not
        /// </summary>
        /// <param name="array">Array to test</param>
        /// <returns>true if empty, otherwise false</returns>
        public static bool isempty(ILBaseArray array)
        {
            return array.IsEmpty;
        }

        /// <summary>
        /// Determines if the supplied argument is a floating point entity.
        /// </summary>
        /// <param name="obj">Object to test</param>
        /// <returns>true if floating point, otherwise false</returns>
        public static bool isfloat(object obj)
        {
            return
                obj is float ||
                obj is double ||
                obj is ILArray<float> ||
                obj is ILArray<double> ||
                obj is ILArray<complex>;
        }

        /// <summary>
        /// Determines if the supplied argument is an integer entity.
        /// </summary>
        /// <param name="obj">Object to test</param>
        /// <returns>true if integer, otherwise false</returns>
        public static bool isinteger(object obj)
        {
            return
                obj is int ||
                obj is uint ||
                obj is ILArray<int> ||
                obj is ILArray<uint>;
        }

        /// <summary>
        /// Determines if the supplied argument is a logical entity.
        /// </summary>
        /// <param name="obj">Object to test</param>
        /// <returns>true if logical, otherwise false</returns>
        public static bool islogical(object obj)
        {
            return
                obj is bool ||
                obj is ILArray<bool>;
        }

        /// <summary>
        /// Determines if the supplied argument is a numeric entity.
        /// </summary>
        /// <param name="obj">Object to test</param>
        /// <returns>true if floating point, otherwise false</returns>
        public static bool isnumeric(object obj)
        {
            if (obj is int ||
                obj is uint ||
                obj is char ||
                obj is byte ||
                obj is float ||
                obj is double ||
                obj is ILArray<int> ||
                obj is ILArray<uint> ||
                obj is ILArray<char> ||
                obj is ILArray<byte> ||
                obj is ILArray<float> ||
                obj is ILArray<double> ||
                obj is ILArray<complex> ||
                obj is ILArray<fcomplex>)
                return true;

            return false;
        }

        /// <summary>
        /// Displays the specified object in the debug window.
        /// </summary>
        /// <param name="arg">Object to display</param>
        public static void disp(object arg)
        {
            Utils.trace("{0}", arg);
        }

        /// <summary>
        /// Displays the specified object in the debug window.
        /// </summary>
        /// <param name="arg">Object to display</param>
        public static void display(object arg)
        {
            disp(arg);
        }


        //
        // --- Diagonal of matrix or create diagonal matrix ---
        //

        /// <summary>
        /// Diagonal of matrix or create diagonal matrix.
        /// </summary>
        /// <param name="arg">Diagonal of matrix or diagonal to create matrix from</param>
        /// <param name="k">Diagonal position</param>
        /// <returns>Diagonal of matrix or matrix created from diagonal</returns>
        public static ILArray<double> diag(ILArray<double> arg, double k = 0)
        {
            int ki = (int)k;
            return ILMath.diag(arg, ki);
        }

        /// <summary>
        /// Diagonal of matrix or create diagonal matrix.
        /// </summary>
        /// <param name="arg">Diagonal of matrix or diagonal to create matrix from</param>
        /// <param name="k">Diagonal position</param>
        /// <returns>Diagonal of matrix or matrix created from diagonal</returns>
        public static ILArray<float> diag(ILArray<float> arg, double k = 0)
        {
            int ki = (int)k;
            return ILMath.diag(arg, ki);
        }

        /// <summary>
        /// Diagonal of matrix or create diagonal matrix.
        /// </summary>
        /// <param name="arg">Diagonal of matrix or diagonal to create matrix from</param>
        /// <param name="k">Diagonal position</param>
        /// <returns>Diagonal of matrix or matrix created from diagonal</returns>
        public static ILArray<double> diag(ILArray<int> arg, double k = 0)
        {
            int ki = (int)k;
            return ILMath.diag(ILMath.todouble(arg), ki);
        }

        /// <summary>
        /// Diagonal of matrix or create diagonal matrix.
        /// </summary>
        /// <param name="arg">Diagonal of matrix or diagonal to create matrix from</param>
        /// <param name="k">Diagonal position</param>
        /// <returns>Diagonal of matrix or matrix created from diagonal</returns>
        public static ILArray<complex> diag(ILArray<complex> arg, double k = 0)
        {
            int ki = (int)k;
            return ILMath.diag(arg, ki);
        }

        /// <summary>
        /// Diagonal of matrix or create diagonal matrix.
        /// </summary>
        /// <param name="arg">Diagonal of matrix or diagonal to create matrix from</param>
        /// <param name="k">Diagonal position</param>
        /// <returns>Diagonal of matrix or matrix created from diagonal</returns>
        public static ILArray<fcomplex> diag(ILArray<fcomplex> arg, double k = 0)
        {
            int ki = (int)k;
            return ILMath.diag(arg, ki);
        }

        /// <summary>
        /// Diagonal of matrix or create diagonal matrix.
        /// </summary>
        /// <param name="arg">Diagonal of matrix or diagonal to create matrix from</param>
        /// <param name="k">Diagonal position</param>
        /// <returns>Diagonal of matrix or matrix created from diagonal</returns>
        public static ILArray<double> diag(ILArray<byte> arg, double k = 0)
        {
            int ki = (int)k;
            return ILMath.diag(ILMath.todouble(arg), ki);
        }

        /// <summary>
        /// Diagonal of matrix or create diagonal matrix.
        /// </summary>
        /// <param name="arg">Diagonal of matrix or diagonal to create matrix from</param>
        /// <param name="k">Diagonal position</param>
        /// <returns>Diagonal of matrix or matrix created from diagonal</returns>
        public static ILArray<double> diag(ILArray<char> arg, double k = 0)
        {
            int ki = (int)k;
            return ILMath.diag(ILMath.todouble(arg), ki);
        }

        /// <summary>
        /// Diagonal of matrix or create diagonal matrix.
        /// </summary>
        /// <param name="arg">Diagonal of matrix or diagonal to create matrix from</param>
        /// <param name="k">Diagonal position</param>
        /// <returns>Diagonal of matrix or matrix created from diagonal</returns>
        public static ILArray<double> diag(ILArray<long> arg, double k = 0)
        {
            int ki = (int)k;
            return ILMath.diag(ILMath.todouble(arg), ki);
        }

        /// <summary>
        /// Diagonal of matrix or create diagonal matrix.
        /// </summary>
        /// <param name="arg">Diagonal of matrix or diagonal to create matrix from</param>
        /// <param name="k">Diagonal position</param>
        /// <returns>Diagonal of matrix or matrix created from diagonal</returns>
        public static ILArray<double> diag(ILArray<short> arg, double k = 0)
        {
            int ki = (int)k;
            return ILMath.diag(ILMath.todouble(arg), ki);
        }
    }
}